package my.json.tool;
import java.text.SimpleDateFormat;
import java.util.*;
import java.lang.reflect.Array;

import org.json.JSONObject;
import org.json.JSONArray;
import my.json.core.JsonAble;

/**
 * Created by IntelliJ IDEA.
 * User: Administrator
 * Date: 2010-10-12
 * Time: 16:54:54
 * To change this template use File | Settings | File Templates.
 */
public class MySon {
    private SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    private ReflectFactory reflectFactory = ReflectFactory.getInstance();
    private final String DefaultValueKey = "_JsonValue_";
    private final String DefaultTypeKey = "_JsonType_";
    private final String DefaultTypeSuffixKey = "_JsonTypeSuffix_";
    
    public JSONObject toJSON(Object obj) throws Exception {
        if (obj == null) {
            return null;
        }

        if (obj instanceof Number || obj instanceof Boolean || obj instanceof String) {//数值,布尔,字符串
            JSONObject json = new JSONObject();
            json.put(DefaultValueKey, obj.toString());
            json.put(DefaultTypeKey, obj.getClass().getName());
            return json;
        }
        if (obj instanceof Date) {//日期
            JSONObject json = new JSONObject();
            json.put(DefaultValueKey, formatter.format((Date) obj));
            json.put(DefaultTypeKey, obj.getClass().getName());
            return json;
        }

        if (obj instanceof JsonAble) {//JsonAble
            JSONObject json = new JSONObject();
            json.put(DefaultValueKey, ((JsonAble) obj).toJSON());
            json.put(DefaultTypeKey, obj.getClass().getName());
            json.put(DefaultTypeSuffixKey, "JsonAble");
            return json;
        }
        if (obj instanceof Object[]) {//array,目前只支持一维数组
            Object[] objarr = (Object[]) obj;
            JSONArray jsonarr = new JSONArray();
            for (int i = 0; i < objarr.length; i++) {
                jsonarr.put(toJSON(objarr[i]));
            }
            JSONObject json = new JSONObject();
            json.put(DefaultValueKey, jsonarr);
            json.put(DefaultTypeKey, obj.getClass().getName());
            json.put(DefaultTypeSuffixKey, "Array");
            return json;
        }
        if (obj instanceof List) {//list
            List objlist = (List) obj;
            JSONArray jsonarr = new JSONArray();
            for (Iterator it = objlist.iterator(); it.hasNext();) {
                jsonarr.put(toJSON(it.next()));
            }
            JSONObject json = new JSONObject();
            json.put(DefaultValueKey, jsonarr);
            json.put(DefaultTypeKey, obj.getClass().getName());
            json.put(DefaultTypeSuffixKey, "List");
            return json;
        }
        if (obj instanceof Set) {//set
            Set objset = (Set) obj;
            JSONArray jsonarr = new JSONArray();
            for (Iterator it = objset.iterator(); it.hasNext();) {
                jsonarr.put(toJSON(it.next()));
            }
            JSONObject json = new JSONObject();
            json.put(DefaultValueKey, jsonarr);
            json.put(DefaultTypeKey, obj.getClass().getName());
            json.put(DefaultTypeSuffixKey, "Set");
            return json;
        }
        if (obj instanceof Map) {//map
            Map objmap = (Map) obj;
            JSONObject jsonobj = new JSONObject();
            Set keyset = objmap.keySet();
            for (Iterator it = keyset.iterator(); it.hasNext();) {
                String key = (String) it.next();
                jsonobj.put(key, toJSON(objmap.get(key)));
            }
            JSONObject json = new JSONObject();
            json.put(DefaultValueKey, jsonobj);
            json.put(DefaultTypeKey, obj.getClass().getName());
            json.put(DefaultTypeSuffixKey, "Map");
            return json;
        }
        throw new Exception("un jsonable type:" + obj.getClass().getName());
    }

    public Object fromJSON(JSONObject json) throws Exception {
        if (json == null) return null;
        JSONObject jsonobj = json;
        Object defaultValue = jsonobj.get(DefaultValueKey);
        String defaultType = (String) jsonobj.get(DefaultTypeKey);
        if (defaultType.equals("java.lang.Byte")) {
            return Byte.valueOf(defaultValue.toString());
        } else if (defaultType.equals("java.lang.Integer")) {
            return Integer.valueOf(defaultValue.toString());
        } else if (defaultType.equals("java.lang.Long")) {
            return Long.valueOf(defaultValue.toString());
        } else if (defaultType.equals("java.lang.Float")) {
            return Float.valueOf(defaultValue.toString());
        } else if (defaultType.equals("java.lang.Double")) {
            return Double.valueOf(defaultValue.toString());
        } else if (defaultType.equals("java.lang.String")) {
            return String.valueOf(defaultValue.toString());
        } else if (defaultType.equals("java.lang.Date")) {
            return formatter.parse(defaultValue.toString());
        } else {
            String suffix = (String) jsonobj.get(DefaultTypeSuffixKey);
            if (suffix.equals("JsonAble")) {
                JSONObject value = (JSONObject) defaultValue;
                JsonAble jsonable =reflectFactory.newInstance(defaultType,JsonAble.class);
                jsonable.fromJSON(value);
                return jsonable;
            } else if (suffix.equals("Map")) {
                JSONObject value = (JSONObject) defaultValue;
                Map map =reflectFactory.newInstance(defaultType,Map.class);
                for (Iterator it = value.keys(); it.hasNext();) {
                    String key = (String) it.next();
                    map.put(key, fromJSON((JSONObject) value.get(key)));
                }
                return map;
            } else if (suffix.equals("List")) {
                JSONArray value = (JSONArray) defaultValue;
                List list = reflectFactory.newInstance(defaultType,List.class);
                for (int i = 0; i < value.length(); i++) {
                    list.add(fromJSON((JSONObject) value.get(i)));
                }
                return list;
            } else if (suffix.equals("Set")) {
                JSONArray value = (JSONArray) defaultValue;
                Set set = reflectFactory.newInstance(defaultType,Set.class);
                for (int i = 0; i < value.length(); i++) {
                    set.add(fromJSON((JSONObject) value.get(i)));
                }
                return set;
            } else if (suffix.equals("Array")) {
                JSONArray value = (JSONArray) defaultValue;
                Class clazz = reflectFactory.getClazz(defaultType.substring(0, defaultType.length() - 1).substring(2)).getJavaClass();
                Object arr = Array.newInstance(clazz, value.length());
                for (int i = 0; i < value.length(); i++) {
                    Array.set(arr, i, fromJSON((JSONObject) value.get(i)));
                }
                return arr;
            }
            throw new Exception("un jsonable type:" + defaultType);
        }
    }
}
